package com.meida.student.app.user.handler;

import com.meida.common.base.entity.EntityMap;
import com.meida.common.base.utils.FlymeUtils;
import com.meida.common.constants.CommonConstants;
import com.meida.common.mybatis.interceptor.SaveInterceptor;
import com.meida.common.mybatis.model.ResultBody;
import com.meida.common.mybatis.query.CriteriaSave;
import com.meida.common.security.OpenHelper;
import com.meida.common.utils.*;
import com.meida.module.bus.client.entity.BusOrder;
import com.meida.module.bus.client.entity.BusSubject;
import com.meida.module.bus.client.entity.BusTutorType;
import com.meida.module.bus.client.enums.*;
import com.meida.module.bus.provider.service.BusOrderService;
import com.meida.module.bus.provider.service.BusSubjectService;
import com.meida.module.bus.provider.service.BusTutorTypeService;
import com.meida.module.bus.provider.utils.MyDateUtils;
import com.meida.module.bus.provider.utils.MyUtils;
import com.meida.module.file.provider.service.SysFileService;
import com.meida.module.system.provider.service.SysExpireStrategyService;
import com.meida.msg.client.entity.MsgReceive;
import com.meida.msg.provider.service.MsgReceiveService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;

/**
 * 用户提交订单
 */
@Component
@Slf4j
public class SubmitOrderHandler implements SaveInterceptor<BusOrder> {

    @Autowired
    private OrderNoUtil orderNoUtil;

    @Autowired
    private BusOrderService busOrderService;

    @Autowired
    private BusTutorTypeService busTutorTypeService;

    @Autowired
    private SysFileService sysFileService;

    @Autowired
    private BusSubjectService busSubjectService;

    @Autowired
    private MsgReceiveService msgReceiveService;

    @Autowired
    private RedisUtils redisUtils;

    @Autowired
    private HttpServletRequest httpServletRequest;

    @Autowired
    private SysExpireStrategyService sysExpireStrategyService;


    @Override
    public ResultBody validate(CriteriaSave cs, EntityMap params) {
        log.error("订单发布参数" + JsonUtils.beanToJson(params));
        //订单类型(1:拍照,2:预约,3:作业无忧)

        Integer orderType = params.getInt("orderType");
        Long subjectId = params.getLong("subjectId");
        String subjectIds = params.get("subjectIds");
        String orderDescribe = params.get("orderDescribe");
        ApiAssert.isNotEmpty("缺少订单参数orderType", orderType);
        ApiAssert.isNotEmpty("缺少订单参数subjectId", subjectId);
        ApiAssert.isNotEmpty("缺少订单参数subjectIds", subjectIds);
        ApiAssert.isNotEmpty("缺少订单参数orderDescribe", orderDescribe);
        //附件Ids
        String fileIds = params.get("fileIds");
        if (orderType.equals(OrderTypeEnum.TakePhotosAskQuestions.getValue())) {
            ApiAssert.allNotNull("请上传图片", fileIds);
        } else {
            ApiAssert.allNotNull("请上传图片或者附件", fileIds);
        }

        return ResultBody.ok();
    }

    @Override
    public void prepare(CriteriaSave criteriaSave, EntityMap entityMap, BusOrder busOrder) {
        //是否保存草稿
        Integer tag = entityMap.getInt("tag", 0);
        Integer orderType = entityMap.getInt("orderType");
        //指定学霸下单
        Long answerUserId = entityMap.getLong("answerUserId");
        //悬赏金额
        BigDecimal rewardAmount = entityMap.getBigDecimal("rewardAmount");
        busOrder.setRewardAmount(rewardAmount);
        Long subjectId = entityMap.getLong("subjectId");
        String subjectIds = entityMap.get("subjectIds");
        List<Long> subjectIdList = MyUtils.stringToLongList(subjectIds);
        busOrder.setPrivateOrder(CommonConstants.DISABLED);
        if (OrderTypeEnum.TakePhotosAskQuestions.getValue() == orderType) {
            //根据subjectId计算订单金额
            BigDecimal amount = busSubjectService.getPriceByIds(subjectIdList);
            busOrder.setOrderAmount(amount);
        }
        if (OrderTypeEnum.BookingTutoring.getValue() == orderType) {
            //根据辅导类型去计算订单金额
            //辅导类型
            Long tutorTypeId = entityMap.getLong("tutorTypeId");
            BusTutorType tutorType = busTutorTypeService.getById(tutorTypeId);
            ApiAssert.isNotEmpty("辅导类型不存在", tutorType);
            Integer chargeType = tutorType.getChargeType();
            //辅导单价
            BigDecimal tutorPrice = tutorType.getTutorPrice();
            //订单金额
            BigDecimal orderAmount;
            //预约日期
            String appointmentDate = entityMap.get("appointmentDate");
            String appointmentTime = entityMap.get("appointmentTime");
            ApiAssert.isNotEmpty("缺少预约辅导订单参数appointmentDate", appointmentDate);
            ApiAssert.isNotEmpty("缺少预约辅导订单参数appointmentTime", appointmentTime);
            if (chargeType.equals(TutorChargeTypeEnum.Time.getValue())) {
                //预约时长
                BigDecimal durationTime = entityMap.getBigDecimal("durationTime");
                ApiAssert.isNotEmpty("缺少预约辅导订单参数durationTime", durationTime);
                orderAmount = tutorPrice.multiply(durationTime);
            } else {
                //按次时即为订单金额
                orderAmount = tutorPrice;
            }
            String appointmentDateTimeStr = appointmentDate + " " + appointmentTime + ":00";
            log.info("SubmitOrderHandler---appointmentDateTimeStr" + appointmentDateTimeStr);
            Date expireTime = DateUtils.strToDate(appointmentDateTimeStr, "yyyy-MM-dd HH:mm:ss");
            log.info("SubmitOrderHandler---expireTime" + expireTime);
            String targetTimezone = httpServletRequest.getHeader("targetTimezone");
            log.info("SubmitOrderHandler---targetTimezone" + targetTimezone);
            if (FlymeUtils.isNotEmpty(targetTimezone)) {
                Date newDate = MyDateUtils.convertTimezone(expireTime, targetTimezone, "UTC");
                log.info("SubmitOrderHandler---newDate" + newDate);
                String newAppointmentDateStr = DateUtils.formatDate(newDate, "yyyy-MM-dd");
                String newAppointmentTimeStr = DateUtils.formatDate(newDate, "HH:mm");
                busOrder.setAppointmentDate(newAppointmentDateStr);
                busOrder.setAppointmentTime(newAppointmentTimeStr);
            }
            busOrder.setOrderAmount(orderAmount);

        }
        if (OrderTypeEnum.HomeWork.getValue().equals(orderType)) {
            //作业无忧类型计算订单金额
            //截止日期
            String appointmentDate = entityMap.get("appointmentDate");
            String appointmentTime = entityMap.get("appointmentTime");
            //预期报价
            BigDecimal expectedAmount = entityMap.getBigDecimal("expectedAmount");
            ApiAssert.isNotEmpty("缺少作业无忧订单参数appointmentDate", appointmentDate);
            ApiAssert.isNotEmpty("缺少作业无忧订单参数expectedAmount", expectedAmount);
            //最低报价金额
            //BusSubject busSubject = busSubjectService.getById(subjectId);
            //BigDecimal minAmount = busSubject.getAmount();
            BigDecimal minAmount = busSubjectService.getPriceByIds(subjectIdList);
            if (FlymeUtils.lt(minAmount, rewardAmount)) {
                ApiAssert.failure("预期报价不能低于" + minAmount);
            }
            busOrder.setOrderAmount(BigDecimal.ZERO);

            if (FlymeUtils.isNotEmpty(answerUserId)) {
                busOrder.setOrderAmount(expectedAmount);
            }
            busOrder.setOrderState(OrderStateZEnum.OrderState1.getValue());

            String appointmentDateTimeStr = appointmentDate + " " + appointmentTime + ":00";
            Date expireTime = DateUtils.strToDate(appointmentDateTimeStr, "yyyy-MM-dd HH:mm:ss");
            String targetTimezone = httpServletRequest.getHeader("targetTimezone");
            Date newDate = MyDateUtils.convertTimezone(expireTime, targetTimezone, "UTC");
            String newAppointmentDateStr = DateUtils.formatDate(newDate, "yyyy-MM-dd");
            String newAppointmentTimeStr = DateUtils.formatDate(newDate, "HH:mm");
            busOrder.setAppointmentDate(newAppointmentDateStr);
            busOrder.setAppointmentTime(newAppointmentTimeStr);
            busOrder.setExpiryTime(newAppointmentDateStr + " " + newAppointmentTimeStr);

        } else {
            //除作业无忧外，未支付的订单都默认-1（草稿箱查询-1）
            busOrder.setOrderState("-1");
        }
        if (tag.equals(1)) {
            //保存草稿箱
            busOrder.setOrderState("-1");
        }
        if (FlymeUtils.isNotEmpty(answerUserId)) {
            busOrder.setPrivateOrder(CommonConstants.ENABLED);
        }
        busOrder.setOrderNo(orderNoUtil.getOrderNo());
        Long userId = OpenHelper.getUserId();
        busOrder.setUserId(userId);
        busOrder.setRewardAmount(rewardAmount);
        //全局配置
        EntityMap config = redisUtils.getConfigMap("SERVICE_FEE_CONFIG");
        //佣金比例
        BigDecimal platformServiceFee = config.getBigDecimal("platformServiceFee");
        BigDecimal commissionRate = new BigDecimal(0.2);
        if (FlymeUtils.isNotEmpty(platformServiceFee)) {
            commissionRate = platformServiceFee.divide(new BigDecimal(100));
        }
        BigDecimal orderAmount = busOrder.getOrderAmount();
        //计算佣金金额(订单金额+悬赏金额)*(1-佣金比例)
        BigDecimal commission = orderAmount.add(rewardAmount).multiply(BigDecimal.ONE.subtract(commissionRate));
        busOrder.setCommission(commission);
        //设置支付状态
        busOrder.setPayState(PayStateEnum.NoPay.getValue());
        //设置封面图,从附件中取图片类型
        String fileIds = entityMap.get("fileIds");
        String coverImg = sysFileService.getCoverImg(fileIds);
        busOrder.setCoverImg(coverImg);
        busOrder.setPayableAmount(orderAmount.add(rewardAmount));
    }

    @Override
    public void complete(CriteriaSave cs, EntityMap params, BusOrder busOrder) {
        Integer orderType = busOrder.getOrderType();
        Long orderId = busOrder.getOrderId();
        if (OrderTypeEnum.BookingTutoring.getValue().equals(orderType)) {
            String appointmentDateStr = busOrder.getAppointmentDate();
            String appointmentTimeStr = busOrder.getAppointmentTime();
            String appointmentDateTimeStr = appointmentDateStr + " " + appointmentTimeStr + ":00";
            log.info("SubmitOrderHandler---appointmentDateTimeStr：" + appointmentDateTimeStr);
            Date expireTime = DateUtils.strToDate(appointmentDateTimeStr, "yyyy-MM-dd HH:mm:ss");
            String redisKey = RedisKeyEnum.OrderCancel.getRedisKey() + orderId;
            sysExpireStrategyService.saveAndToRedis(redisKey, orderId, RedisKeyEnum.OrderCancel.getRedisTargetType(), expireTime);
        }
        //订单节点通知和出价过期处理
        if (OrderTypeEnum.HomeWork.getValue().equals(orderType)) {
            //订单节点通知
            String msgTitle = "作业无忧待出价通知";
            String msgContent = "恭喜您！您的作业无忧上传成功待学霸出价，请及时查看订单！感谢您使用留同学APP";
            MsgReceive msgReceive = msgReceiveService.sendMsgReceiveNotice(BusOrder.class.getSimpleName(), busOrder.getUserId(), msgTitle, msgContent);
            busOrderService.orderPushMessage(msgReceive, msgTitle, msgContent);
            String orderState = busOrder.getOrderState();
            if (!"-1".equals(orderState)) {
                //作业无忧出价超时处理
                EntityMap quotedPriceMap = redisUtils.getConfigMap("QUOTED_PRICE");
                Date createTime = busOrder.getCreateTime();
                //报价时长
                Integer quotedHours = quotedPriceMap.getInt("quotedHours");
                Date expireTime = MyDateUtils.addHours(createTime, quotedHours);
                String redisKey = RedisKeyEnum.OrderCancel.getRedisKey() + orderId;
                sysExpireStrategyService.saveAndToRedis(redisKey, orderId, RedisKeyEnum.OrderCancel.getRedisTargetType(), expireTime);
            }
        }
    }

    public static void main(String[] args) {
        //格式化显示日期(目标时区的预约时间),需要转成UTC时间
        /*String appointmentDateTimeStr = "2022-04-25 13:15:00";
        log.info("SubmitOrderHandler---appointmentDateTimeStr" + appointmentDateTimeStr);
        Date expireTime = DateUtils.strToDate(appointmentDateTimeStr, "yyyy-MM-dd HH:mm:ss");
        log.info("SubmitOrderHandler---expireTime" + expireTime);
        String targetTimezone = "US/Eastern";
        log.info("SubmitOrderHandler---targetTimezone" + targetTimezone);
        if (FlymeUtils.isNotEmpty(targetTimezone)) {
            Date newDate = MyDateUtils.convertTimezone(expireTime, targetTimezone,"UTC");
            log.info("SubmitOrderHandler---newDate" + newDate);
            String newAppointmentDateStr = DateUtils.formatDate(newDate, "yyyy-MM-dd");
            String newAppointmentTimeStr = DateUtils.formatDate(newDate, "HH:mm");
            System.out.println(newAppointmentDateStr);
            System.out.println(newAppointmentTimeStr);
        }*/

        String appointmentDateTimeStr = "2022-04-25 18:15:00";
        Date date = DateUtils.strToDate(appointmentDateTimeStr, "yyyy-MM-dd HH:mm:ss");
        Date newDate = MyDateUtils.convertTimezone(date, "GTC","US/Eastern");
        String newAppointmentDate = DateUtils.formatDate(newDate, "yyyy-MM-dd");
        String newAppointmentTime = DateUtils.formatDate(newDate, "HH:mm");
        String dayOfWeek = DateUtils.getDayOfWeek(DateUtils.formatDate(newAppointmentDate));
        System.out.println(newAppointmentDate);
        System.out.println(newAppointmentTime);
        System.out.println(dayOfWeek);
    }

}
